home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1994 September / macformat-004.iso / Shareware City / Graphics / VideoToolbox ƒ / VideoToolboxSources / RectToAddress.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-07  |  6.7 KB  |  158 lines  |  [TEXT/KAHL]

  1. /* RectToAddress.c
  2. Finds the 32-bit memory address of a pixel in a PixMap or BitMap. Completely
  3. general: multiple screens, on- or off-screen, BitMaps, PixMaps, and any pixel
  4. size. Doesn't require color quickdraw. The optional parameters return the row
  5. length of the pixmap or bitmap, the pixel size, and the offset in bits into the
  6. byte (for pixels that are smaller than a byte).
  7.  
  8. The returned address corresponds to the upper-left pixel in *rectPtr in
  9. *pixMapPtr, AFTER clipping by the bounds associated with the pix/bitmap: If
  10. it's an off-screen Pix/BitMap it clips *rectPtr to the PixMap bounds; if it's
  11. on-screen it clips *rectPtr to that screen device. The returned address is NULL
  12. if *rectPtr is empty after clipping.
  13.  
  14. You should only access the address returned by RectToAddress inside a block of
  15. code that operates in 32-bit addressing mode. Use SwapMMUMode(), which is
  16. documented in Apple's Inside Macintosh.
  17.  
  18. unsigned char *RectToAddress(PixMap *pixMapPtr,Rect *rectPtr,short *rowBytesPtr, 
  19.     short *pixelSizePtr,short *bitsOffsetPtr)
  20.  
  21. *pixMapPtr is the PixMap or BitMap that you're working in.
  22. *rectPtr is the Rect you're interested in, in local coordinates. 
  23.     Will be clipped by pixmap/device bounds.
  24. *rowBytesPtr optionally returns rowBytes.
  25. *pixelSizePtr optionally returns pixelSize.
  26. *bitsOffsetPtr optionally returns positive offset in bits from returned
  27.     byte address to the location specified by upper left corner of rectPtr
  28.  
  29. Copyright ©1989-1994 Denis G. Pelli.
  30.  
  31. HISTORY:
  32. 4/89    dgp    v. 1.0 extracted it from CopyBitsQuickly.
  33. 2/91    dgp    v. 1.1 no longer requires color quickdraw.
  34. 4/5/91    dgp    v. 1.2 fixed overflow bug reported by Brady Duga.
  35. 8/24/91    dgp    Made compatible with THINK C 5.0.
  36. 4/27/92    dgp    Though I haven't experienced any problems I took the advice of Apple's
  37.             Inside Mac VI and now get the pixmap base address by means of the new
  38.             GetPixBaseAddr() if that trap is available.
  39. 7/13/92    dgp    enhanced the documentation above. Removed support for THINK C version 4.
  40. 1/11/93    dgp only call GetPixBaseAddr() for PixMap, not for BitMap.
  41. 2/7/93    dgp    return NULL if supplied pix/bitmap pointer is NULL.
  42. 3/14/93    dgp    Use GetPixBaseAddr() only if the working version is present, i.e.
  43.             not the first version of 32-bit QuickDraw.
  44. 4/1/93    dgp    Changed test for valid GetPixBaseAddr() to require version gestalt32BitQD13 
  45.             or later, as specified by New Tech Note "Color QuickDraw Q&As".
  46. 4/21/93    dgp    Now always return a 32-bit address, even under System 6.
  47.             Wrote GetPixBaseAddr32() which is a more-dependable substitute for
  48.             Apple's GetPixBaseAddr, and accepts bit/pixmaps to boot.
  49. 4/27/93    dgp    Josh discovered a bug; RectToAddress was finding the device that
  50.             held the upper left corner of the rect, BEFORE clipping by the pixmap,
  51.             which resulted in a null rect when the wrong device was later clipped
  52.             by the pixmap. Now I do the right thing, which is to find the device
  53.             that holds the upper left corner of the pixmap. Also, I now always
  54.             return the clipping to the user, which wasn't being done consistently,
  55.             e.g. never for bitmaps.
  56. 4/11/94    dgp    I suspect (but didn't test) that what takes so long in RectToAddress 
  57.             is the call to Apple's GetMaxDevice(), so I now optionally replace that
  58.             by a call to my GetRectDevice(), which is a new routine in GetWindowDevice.c.
  59. */
  60. #include "VideoToolbox.h"
  61.     
  62. Ptr GetPixBaseAddr32(PixMap **pm)
  63. // Returns the 32-bit address of the pixels/bits in a pix/bitmap.
  64. {
  65.     Ptr address;
  66.     long qD;
  67.     GDHandle device;
  68.     short i;
  69.     
  70.     // Apple's GetPixBaseAddr() did not work in the early versions of 32-bit QuickDraw
  71.     Gestalt(gestaltQuickdrawVersion,&qD);
  72.     if(qD>=gestalt32BitQD13 && ((**pm).rowBytes&0x8000))
  73.         return GetPixBaseAddr(pm);    // Guaranteed to be 32-bit.
  74.     address=(**pm).baseAddr;
  75.     if(qD>=gestalt8BitQD){
  76.         // If it's the base address of a screen then it's a 32-bit address.
  77.         for(i=0;;i++){
  78.             device=GetScreenDevice(i);
  79.             if(device==NULL)break;
  80.             if(address==(**(**device).gdPMap).baseAddr)return address;
  81.         }
  82.     }
  83.     // Otherwise it must be in RAM and we should strip it, 
  84.     // since we may be in 24-bit mode.
  85.     address=StripAddress(address);
  86.     return address;
  87. }
  88.  
  89. unsigned char *RectToAddress(PixMap *pixMapPtr,Rect *rectPtr,short *rowBytesPtr, 
  90.     short *pixelSizePtr,short *bitsOffsetPtr)
  91. /*
  92. *pixMapPtr is the PixMap or BitMap that you're working in.
  93. *rectPtr is the Rect you're interested in, in local coordinates. 
  94.     Will be clipped by pixmap/device bounds.
  95. *rowBytesPtr optionally returns rowBytes.
  96. *pixelSizePtr optionally returns pixelSize.
  97. *bitsOffsetPtr optionally returns positive offset in bits from returned
  98.     byte address to the location specified by upper left corner of rectPtr
  99. */
  100. {
  101.     GDHandle device,mainDevice;
  102.     Rect rect,smallRect;
  103.     register Ptr address;
  104.     short notEmpty;
  105.     long x0,y0;
  106.     long qD;
  107.     
  108.     if(pixMapPtr==NULL)return NULL;
  109.     Gestalt(gestaltQuickdrawVersion,&qD);
  110.     x0=pixMapPtr->bounds.left;
  111.     y0=pixMapPtr->bounds.top;
  112.     if(qD>=gestalt8BitQD)mainDevice=GetMainDevice();
  113.     else mainDevice=NULL;
  114.     address=GetPixBaseAddr32(&pixMapPtr);
  115.     if(address==NULL)return NULL;
  116.     if(mainDevice != NULL && address == (*(*mainDevice)->gdPMap)->baseAddr){
  117.         // When there are multiple screens, all windows refer to main device baseAddr
  118.         // so we have to figure out which is the actual device.
  119.         rect = *rectPtr;
  120.         OffsetRect(&rect,-x0,-y0);        /* convert to global coordinates */
  121.         // Find device that displays the upper left pixel of PixMap
  122.         SetRect(&smallRect,-x0,-y0,-x0+1,-y0+1);    // global coordinates
  123.         if(0)device = GetMaxDevice(&smallRect);        // I wonder which is quicker.
  124.         else device = GetRectDevice(&smallRect);
  125.         if(device==NULL)return NULL;
  126.         pixMapPtr = *(*device)->gdPMap;    /* Use the DEVICE'S PixMap */
  127.         address=pixMapPtr->baseAddr;
  128.         notEmpty=SectRect(&pixMapPtr->bounds,&rect,&rect);
  129.         *rectPtr=rect;                    // Clip user's rect too.
  130.         OffsetRect(rectPtr,x0,y0);        // convert that back to local coordinates
  131.                                         // convert ours to device coordinates
  132.         OffsetRect(&rect,-(*device)->gdRect.left,-(*device)->gdRect.top);
  133.     }
  134.     else {
  135.         /* Just clip and convert to global coordinates */
  136.         rect = *rectPtr;
  137.         notEmpty=SectRect(&pixMapPtr->bounds,&rect,&rect);
  138.         *rectPtr=rect;                    // Clip user's rect too.
  139.         OffsetRect(&rect,-x0,-y0);        // convert to global coordinates
  140.     }
  141.     address += rect.top*(long)(pixMapPtr->rowBytes & 0x1fff);
  142.     if(pixMapPtr->rowBytes & 0x8000){                    /* Pixmap or Bitmap? */
  143.         // Pixmap
  144.         address += (rect.left*(long)pixMapPtr->pixelSize)/8;
  145.         if(bitsOffsetPtr != NULL) *bitsOffsetPtr=(rect.left*(long)pixMapPtr->pixelSize)%8;
  146.         if(pixelSizePtr != NULL) *pixelSizePtr=pixMapPtr->pixelSize;
  147.     }
  148.     else{
  149.         // Bitmap
  150.         address += rect.left/8;        
  151.         if(bitsOffsetPtr != NULL) *bitsOffsetPtr=rect.left%8;
  152.         if(pixelSizePtr != NULL) *pixelSizePtr=1;
  153.     }
  154.     if(rowBytesPtr != NULL) (*rowBytesPtr)=pixMapPtr->rowBytes & 0x1fff;
  155.     if(!notEmpty)address=NULL;    
  156.     return (unsigned char *) address;
  157. }
  158.